#ifndef INIT_H
#define INIT_H
#include<sql.h>
#include<util.h>
#include <netinet/in.h>
#include<pcap.h>
#include<sstream>
#include<ThreadPool.h>
#include <iomanip>
#include <sstream>
ThreadPool threadPool;


//int number=getConfigInt("libpcap:number");
int number=5;

//int number=10;
//帧数量
int pck_number=0;
//流量
int flow=0;

//回调函数——对数据包进行分析
void callback(u_char* user, const struct pcap_pkthdr* pkt_header, const u_char* pkt_content) {

    //信息封装类
    Info info;
    pcap_t* pcap_handle = (pcap_t*)user;
    struct tm *p_tm;
    char time_str[30];
    p_tm = localtime((const time_t *)&(pkt_header->ts.tv_sec));
    snprintf(time_str, sizeof(time_str), "%04d-%02d-%02d %02d:%02d:%02d",p_tm->tm_year + 1900, p_tm->tm_mon + 1, p_tm->tm_mday,p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec);
    //printf("%s\t%d\t", time_str, pkt_header->len);
    pck_number++;
    flow+=pkt_header->len;
    //封装时间
    info.time=time_str;
    //封装长度
    std::stringstream ss_length;
    ss_length<<pkt_header->len;
    info.length=ss_length.str();

    if(pcap_datalink(pcap_handle)==is_ether){
        const ether_header* ether_header=parse_ether_header(pkt_content);
        u_int16_t net_type=ether_header->ether_type;
        //封装mac
        std::stringstream d_mac_ss;
            std::stringstream s_mac_ss;

            for (int i = 0; i < 6; ++i) {
                d_mac_ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(ether_header->ether_dhost[i]);
                s_mac_ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(ether_header->ether_shost[i]);
                if (i != 5) {
                    d_mac_ss << ":";
                    s_mac_ss << ":";
                }
            }
        std::string d_mac = d_mac_ss.str();
        std::string s_mac = s_mac_ss.str();
        info.d_mac=d_mac;
        info.s_mac=s_mac;

        if(net_type==is_ip){
            const ip_header* ip_header=parse_ip_header(pkt_content+ether_header_length);
            //封装ip
            info.s_ip=inet_ntoa(ip_header->ip_souce_address);
            info.d_ip=inet_ntoa(ip_header->ip_destination_address);

            if(ip_header->ip_protocol==is_tcp){
                const tcp_header* tcp_header=parse_tcp_header(pkt_content+ether_header_length+ip_header_length);
                //封装端口

                std::stringstream ss_source_port;
                std::stringstream ss_destination_port;

                ss_source_port << ntohs(tcp_header->tcp_source_port);
                ss_destination_port << ntohs(tcp_header->tcp_destination_port);

                info.s_port=ss_source_port.str();
                info.d_port= ss_destination_port.str();

                //解析http内容
                //封装负载
                 info.payload=parse_http1_1(pkt_content+ether_header_length+ip_header_length+tcp_header_length,pkt_header->len);

                //封装协议类型
                info.protocol="http";

            }

            if(ip_header->ip_protocol==is_udp){
                const udp_header* udp_header= parse_udp_header(pkt_content+ether_header_length+ip_header_length);
                //封装端口
                std::stringstream ss_source_port;
                std::stringstream ss_destination_port;

                ss_source_port << ntohs(udp_header->udp_source_port);
                ss_destination_port << ntohs(udp_header->udp_destination_port);

                info.s_port=ss_source_port.str();
                info.d_port= ss_destination_port.str();
            }
        }
        if(net_type==is_arp){printf("arp\n"); parse_arp_header(pkt_content);}
    }
    if(count1>number-1){
        infoList.clear();
        count1=0;
    }

    infoList.push_back(info);
    count1++;
}


//捕获一批数据包并解析
int capture_package(){
    //1.得到网络接口
    const char*dev;
    dev=get_local_net();
//    2.打开网络接口
//    pcap_t* pcap_handle=NULL;
//    pcap_handle=open_net(dev);

    char errbuf[1024];
    pcap_t *pcap_handle=pcap_open_offline("http.pcap",errbuf);
    if(pcap_handle==NULL){
        throw std::runtime_error("离线文件打开失败");
    }

    //3.编译并加入过滤规则
//    struct bpf_program fp;
//    pcap_compile(pcap_handle, &fp, getConfigChar("libpcap:filter_rule"), 0, PCAP_NETMASK_UNKNOWN);
//    int result=pcap_setfilter(pcap_handle,&fp);
//    if(result==-1){
//        printf("过滤规则设置失败！\n");
//        return 0;
//    }
//    printf("数据包捕获等待中......\n");

//    if (pcap_loop(pcap_handle, number, callback, (unsigned char*)pcap_handle) < 0) {
//        printf("抓包错误: %s\n", pcap_geterr(pcap_handle));
//        return 0;
//    }
    const unsigned char *packetinfo;    // 数据包内容
    struct pcap_pkthdr pkt_header;      // 数据包头部信息结构体
    int i=1;
     while ((packetinfo = pcap_next(pcap_handle, &pkt_header)) != NULL){
         std::cout<<"\n----------------------------------数据包"<<i<<"-----------------------------------------------------"<<std::endl;
         callback((u_char *)pcap_handle,&pkt_header,packetinfo);
         i++;
     }

}

void start(){

//    while(true){
        capture_package();//批量抓取
        extern std::vector<Info> infoMinList;//待插入信息队列
        for(const auto& info : infoList){
            std::stringstream ss;
            ss <<info.d_mac<<"---"<<info.s_mac<<"---"<< info.s_ip<<"---"<<info.s_port<<"---"<<info.d_ip<<"---"<<info.d_port<<"---"<<info.time<<"---"<<info.length<<"---"<<
                 info.payload;
            std::cout<<"封装信息:"+ss.str()<<std::endl;
            Info  save_info(info.s_mac,info.d_mac,info.s_ip,info.d_ip,info.s_port,info.d_port,info.length,info.time,info.payload,info.protocol);

            threadPool.submit(insert,save_info);

        }
        std::cout<<"累积流量大小："<<flow<<std::endl;
        std::cout<<"累积帧数："<<pck_number<<std::endl;
//    }

}

//}
#endif // INIT_H
